package com.sdleyou.treepro.common.service.impl;

import com.sdleyou.treepro.common.exception.ServiceException;
import com.sdleyou.treepro.common.model.convert.UserPropDO2UserPropVOConverter;
import com.sdleyou.treepro.common.model.dao.UserDO;
import com.sdleyou.treepro.common.model.dao.UserPropDO;
import com.sdleyou.treepro.common.model.enums.ErrorCodeEnum;
import com.sdleyou.treepro.common.model.vo.*;
import com.sdleyou.treepro.common.service.*;
import com.sdleyou.treepro.common.utils.DateUtil;
import com.sdleyou.treepro.common.utils.IdGen;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class UserPropManagerImpl implements UserPropManager {

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private UserManager userManager;
    @Autowired
    private UserMissionManager missionManager;
    @Autowired
    private UserPetManager petManager;
    @Autowired
    private UserTreeManager userTreeManager;
    @Autowired
    private PropManager propManager;
    @Autowired
    private UserMessageManager userMessageManager;

    /**
     * 用户道具列表
     *
     * @param userId
     * @return
     */
    @Override
    public List<UserPropVO> getUserPropList(String userId) {
        Query query = new Query(Criteria.where("user_id").is(userId));
        List<UserPropDO> userPropDOS = mongoTemplate.find(query, UserPropDO.class);
        if (userPropDOS == null) {
            throw new ServiceException(ErrorCodeEnum.E100.code(), "用户不存在");
        }
        return userPropDOS.stream().map(UserPropDO2UserPropVOConverter::convert).collect(Collectors.toList());
    }

    /**
     * 获取单个道具信息
     */
    @Override
    public UserPropVO getUserPropInfo(String propId) {
        Query query = new Query(Criteria.where("prop_id").is(propId));
        UserPropDO userPropDO = mongoTemplate.findOne(query, UserPropDO.class);
        UserPropVO userPropVO = new UserPropVO();
        if (userPropDO != null) {
            BeanUtils.copyProperties(userPropDO, userPropVO);
        }
        return userPropVO;
    }

    /**
     * 给自己使用道具
     *
     * @param userId
     * @param propType
     * @return
     */
    @Override
    public Map<String, String> useProp(String userId, String propType, Integer multiple) {
        return usePropMethod(userId, propType, null, multiple);
    }

    /**
     * 给好友使用道具
     *
     * @param userId
     * @param propType
     * @param toUser
     * @return
     */
    @Override
    public Map<String, String> useProp(String userId, String propType, String toUser, Integer multiple) {
        return usePropMethod(userId, propType, toUser, multiple);
    }

    /**
     * 使用道具
     *
     * @param userId
     * @param propType
     */
    private Map<String, String> usePropMethod(String userId, String propType, String toUser, Integer multiple) {
        UserVO userVO;
        boolean self = true; //是否给自己用道具
        if (toUser == null) {
            userVO = userManager.userInfo(userId);
        } else {
            userVO = userManager.userInfo(toUser);
            self = false;
        }
        if (userVO == null) {
            throw new ServiceException(ErrorCodeEnum.E100.code(), "用户不存在");
        }

        Query q = new Query(Criteria.where("user_id").is(userId).and("prop_type").is(propType));
        UserPropDO prop = mongoTemplate.findOne(q, UserPropDO.class);
        if (prop == null) {
            throw new ServiceException(ErrorCodeEnum.E401.code(), "道具不存在");
        }

        Map<String, String> map = new HashMap();
        if ("MANURE".equals(propType)) {
            //肥料 土地肥沃度增加10
            Integer propNum = prop.getPropNum();
            if (propNum < 0) {
                throw new ServiceException(ErrorCodeEnum.E400.code(), "道具数量不足");
            }
            Integer fertility = userVO.getFertility();
            if (fertility == 100) {
                throw new ServiceException(ErrorCodeEnum.E402.code(), "土地肥沃值已满");
            }
            if (fertility + prop.getPropValue() > 100) {
                fertility = 100;
            } else {
                fertility += prop.getPropValue();
            }
            Update update = new Update();
            update.set("fertility", fertility);
            Query query = new Query(Criteria.where("user_id").is(userVO.getUserId()));
            mongoTemplate.updateFirst(query, update, UserDO.class);

            subProp(userId, propType, 1);
            if (!self) {
                missionManager.updateMission(userId, "fertilizer", null);
                UserVO u = userManager.userInfo(userId);
                addMessage(toUser, userId, u.getNickname(), "给你施肥了");
            } else {
                addMessage(userId, null, null, "使用肥料土地肥沃度+" + prop.getPropValue());
            }
            map.put("info", prop.getPropEffect() + prop.getPropValue());
        } else if ("WATER".equals(propType)) {
            //水滴 固定使用1滴 成长值=水滴*肥沃值
            Integer propNum = prop.getPropNum();
            if (propNum < 0) {
                throw new ServiceException(ErrorCodeEnum.E400.code(), "道具数量不足");
            }
            DecimalFormat df = new DecimalFormat("0.00");//格式化小数
            String num = df.format(userVO.getFertility() * prop.getPropValue() / 100);

            //UserTreeVO treeInfo = userTreeManager.getTreeInfo(userVO.getUserId(), null);
            userTreeManager.addValue(userVO.getUserId(), userVO.getTreeId(), Double.valueOf(num));
            subProp(userId, propType, 1);
            String notice = null;
            if (!self) {
                missionManager.updateMission(userId, "water", null);
                UserVO u = userManager.userInfo(userId);
                addMessage(toUser, userId, u.getNickname(), "给你浇水了");
            } else {
                addMessage(userId, null, null, "浇水1滴树苗成长" + num);
                //增加累计成长值
                userManager.addTotalGrow(userId, Double.valueOf(num).intValue());
            }
            map.put("info", prop.getPropEffect() + num);
            //增加养殖信息
            userTreeManager.addTreePlantInfo(userVO.getUserId(), userVO.getTreeId(), userId, prop.getPropId(), "浇水5滴树苗成长" + num);
        } else if ("FOOD".equals(propType)) {
            //干粮 使用后宠物出门寻宝
            Integer propNum = prop.getPropNum();
            if (propNum < 1) {
                throw new ServiceException(ErrorCodeEnum.E400.code(), "道具数量不足");
            }
            petManager.petHunt(userId);
            subProp(userId, propType, 1);
            //完成任务
            missionManager.updateMission(userId, "feed", null);
            map.put("info", prop.getPropEffect());
        } else if ("PESTICIDE".equals(propType)) {
            //除虫剂 为树苗除虫
            Integer propNum = prop.getPropNum();
            if (propNum < 1) {
                throw new ServiceException(ErrorCodeEnum.E400.code(), "道具数量不足");
            }
            UserTreeVO treeInfoById = userTreeManager.getTreeInfoById(userVO.getUserId(), userVO.getTreeId());
            if (treeInfoById.getWormNum() <= 0) {
                throw new ServiceException(ErrorCodeEnum.E403.code(), "该树不需要除虫");
            }
            userTreeManager.subWormNum(userVO.getUserId(), userVO.getTreeId());
            subProp(userId, propType, 1);
            map.put("info", prop.getPropEffect());
            if (!self) {
                missionManager.updateMission(userId, "pest", null);
                UserVO u = userManager.userInfo(userId);
                addMessage(toUser, userId, u.getNickname(), "给你灭虫了");
            } else {
                addMessage(userId, null, null, "使用杀虫剂灭虫");
            }
            //增加养殖信息
            userTreeManager.addTreePlantInfo(userVO.getUserId(), userVO.getTreeId(), userId, prop.getPropId(), "使用杀虫剂灭虫了");
        }
        return map;
    }

    /**
     * 添加消息
     */
    private void addMessage(String userId, String friendId, String userName, String content) {
        MessageVO messageVO = new MessageVO();
        messageVO.setType("FRIENDS");
        messageVO.setUserId(userId);
        messageVO.setUserName(userName);
        messageVO.setContent(content);
        messageVO.setFriendId(friendId);
        userMessageManager.create(messageVO);
    }

    /**
     * 增加道具
     *
     * @param userId
     * @param propType
     * @param num
     * @return
     */
    @Override
    public Map<String, String> addProp(String userId, String propType, Integer num) {
        Query query = new Query(Criteria.where("user_id").is(userId).and("prop_type").is(propType));
        UserPropDO userPropDO = mongoTemplate.findOne(query, UserPropDO.class);
        if (userPropDO == null) {
            UserPropDO userProp = new UserPropDO();
            userProp.setPropId(IdGen.uuid());
            userProp.setUserId(userId);
            userProp.setPropType(propType);

            //查询道具信息存入表中
            PropVO prop = propManager.findOne(propType);
            userProp.setPropName(prop.getPropName());
            userProp.setPropDesc(prop.getPropDesc());
            userProp.setPropEffect(prop.getPropEffect());
            userProp.setPropValue(prop.getPropValue());
            userProp.setPropIcon(prop.getPropIcon());
            userProp.setPropImage(prop.getPropImage());
            userProp.setCanBuy(prop.getCanBuy());

            userProp.setPropNum(num);
            userProp.setGmtCreate(DateUtil.toString(DateUtil.getDateline(), "yyyy-MM-dd HH:mm"));
            userProp.setGmtModified(DateUtil.toString(DateUtil.getDateline(), "yyyy-MM-dd HH:mm"));
            mongoTemplate.insert(userProp);
        } else {
            Update update = new Update();
            update.set("prop_num", userPropDO.getPropNum() + num);
            mongoTemplate.updateFirst(query, update, UserPropDO.class);
        }
        Map<String, String> map = new HashMap<>();
        map.put("type", "add");
        map.put("propType", propType);
        map.put("num", num + "");
        return map;
    }

    /**
     * 减少道具
     */
    @Override
    public Map<String, String> subProp(String userId, String propType, Integer num) {
        Query query = new Query(Criteria.where("user_id").is(userId).and("prop_type").is(propType));
        UserPropDO userPropDO = mongoTemplate.findOne(query, UserPropDO.class);
        if (userPropDO != null) {
            Integer currentNum = userPropDO.getPropNum();
            if (num > currentNum) {
                throw new ServiceException(ErrorCodeEnum.E400.code(), "道具数量不足");
            }
            Update update = new Update();
            update.set("prop_num", userPropDO.getPropNum() - num);
            mongoTemplate.updateFirst(query, update, UserPropDO.class);
            Map<String, String> map = new HashMap<>();
            map.put("type", "sub");
            map.put("propType", propType);
            map.put("num", num + "");
            return map;
        }
        return null;
    }

    /**
     * 更新道具数据
     */
    @Override
    public void updateUserProp(String userId) {
        List<PropVO> propVOS = propManager.propList();
        for (PropVO propVO : propVOS) {
            if (propVO != null) {
                addProp(userId, propVO.getPropType(), 0);
            }
        }
    }

    /**
     * 更新道具信息
     */
    @Override
    public void update(String userId) {
        List<PropVO> propVOS = propManager.propList();
        for (PropVO prop : propVOS) {
            if (prop != null) {
                Query query = new Query(Criteria.where("user_id").is(userId).and("prop_type").is(prop.getPropType()));
                Update update = new Update();
                update.set("prop_name", prop.getPropName());
                update.set("prop_desc", prop.getPropDesc());
                update.set("prop_effect", prop.getPropEffect());
                update.set("prop_value", prop.getPropValue());
                update.set("prop_icon", prop.getPropIcon());
                update.set("prop_image", prop.getPropImage());
                update.set("can_buy", prop.getCanBuy());
                mongoTemplate.updateFirst(query, update, UserPropDO.class);
            }
        }
    }
}
